use crate::app::event::Event;
use crate::app::state::{Consumed, SessionHelper};
use crate::app::DynError;
use crate::sketchbook::data_structs::{LayoutData, LayoutNodeData};
use crate::sketchbook::event_utils::{make_reversible, mk_model_event, mk_model_state_change};
use crate::sketchbook::ids::LayoutId;
use crate::sketchbook::layout::NodePosition;
use crate::sketchbook::model::ModelState;
use crate::sketchbook::JsonSerde;
const ADD_LAYOUT_PATH: &str = "add";
const UPDATE_POSITION_PATH: &str = "update_position";
const REMOVE_LAYOUT_PATH: &str = "remove";
impl ModelState {
pub(super) fn perform_layout_event(
&mut self,
event: &Event,
at_path: &[&str],
) -> Result<Consumed, DynError> {
let component_name = "model/layout";
if Self::starts_with(ADD_LAYOUT_PATH, at_path).is_some() {
Self::assert_path_length(at_path, 1, component_name)?;
self.event_add_layout(event)
} else {
Self::assert_path_length(at_path, 2, component_name)?;
let layout_id_str = at_path.first().unwrap();
let layout_id = self.get_layout_id(layout_id_str)?;
self.event_modify_layout(event, &at_path[1..], layout_id)
}
}
pub(super) fn event_add_layout(&mut self, event: &Event) -> Result<Consumed, DynError> {
let component_name = "model/layout";
let payload = Self::clone_payload_str(event, component_name)?;
let layout_data = LayoutData::from_json_str(payload.as_str())?;
let layout_id_str = layout_data.id;
let layout_id = self.generate_layout_id(&layout_id_str, Some(1));
let name = layout_data.name;
self.add_layout_copy(layout_id, &name, &Self::get_default_layout_id())?;
let reverse_at_path = ["layout", &layout_id_str, "remove"];
let reverse_event = mk_model_event(&reverse_at_path, None);
Ok(make_reversible(event.clone(), event, reverse_event))
}
pub(super) fn event_modify_layout(
&mut self,
event: &Event,
at_path: &[&str],
layout_id: LayoutId,
) -> Result<Consumed, DynError> {
let component_name = "model/layout";
if Self::starts_with(UPDATE_POSITION_PATH, at_path).is_some() {
let payload = Self::clone_payload_str(event, component_name)?;
let new_node_data = LayoutNodeData::from_json_str(payload.as_str())?;
let var_id = self.get_var_id(new_node_data.variable.as_str())?;
let new_position = NodePosition(new_node_data.px, new_node_data.py);
let orig_pos = self.get_node_position(&layout_id, &var_id)?.clone();
let orig_pos_data =
LayoutNodeData::new(layout_id.as_str(), var_id.as_str(), orig_pos.0, orig_pos.1);
let new_pos_data = LayoutNodeData::new(
layout_id.as_str(),
var_id.as_str(),
new_node_data.px,
new_node_data.py,
);
if new_position == orig_pos {
return Ok(Consumed::NoChange);
}
self.update_position(&layout_id, &var_id, new_node_data.px, new_node_data.py)?;
let state_change = mk_model_state_change(&["layout", "update_position"], &new_pos_data);
let mut reverse_event = event.clone();
reverse_event.payload = Some(orig_pos_data.to_json_str());
Ok(make_reversible(state_change, event, reverse_event))
} else if Self::starts_with(REMOVE_LAYOUT_PATH, at_path).is_some() {
Self::assert_payload_empty(event, component_name)?;
let layout = self.get_layout(&layout_id)?;
let layout_data = LayoutData::from_layout(&layout_id, layout);
self.remove_layout(&layout_id)?;
let state_change = mk_model_state_change(&["layout", "remove"], &layout_data);
Ok(Consumed::Irreversible {
state_change,
reset: true,
})
} else {
Self::invalid_path_error_specific(at_path, component_name)
}
}
}